package com.ruoyi.binance.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.binance.api.OrderApi;
import com.ruoyi.binance.dingding.DingDingSendMsgUtils;
import com.ruoyi.binance.domain.*;
import com.ruoyi.binance.mapper.*;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;

@Component
public class AsyncAveragePrice {

    @Autowired
    private BinanceMinKMapper stockMinKMapper;
    @Autowired
    private BinanceMinAverageMapper binanceMinAverageMapper;
    @Autowired
    private BinancePriceMonitoringMapper stockPriceMonitoringMapper;
    @Value("${stock.dingdingMessage}")
    private boolean dingdingMessage;
    @Autowired
    private BinanceDingdingMessageMapper stockDingdingMessageMapper;
    @Autowired
    private BinanceTransactionOrderMapper binanceTransactionOrderMapper;
    @Autowired
    private BinanceTransactionConfMapper binanceTransactionConfMapper;
    @Autowired
    private Binance15minAverageMapper binance15minAverageMapper;
    @Autowired
    private Binance30minAverageMapper binance30minAverageMapper;
    @Autowired
    private BinanceHourAverageMapper binanceHourAverageMapper;
    @Autowired
    private Binance15minDayAveMapper binance15minDayAveMapper;

    @Async
    public void getAveragePrice(Long confId, String code, Date time, BigDecimal close, BigDecimal open) {
        BinancePriceMonitoring stockPriceMonitoring = stockPriceMonitoringMapper.selectBinancePriceMonitoringByCode(code);
        if (stockPriceMonitoring == null) {
            return;
        }
        //根据监控均价类型赋值均价
        Binance15minDayAve binance15minDayAve = binance15minDayAveMapper.selectBinance15minDayAveByCodeAndTime(code, DateUtils.getFormatTime(time));
        BigDecimal averagePriceDay = binance15minDayAve.getPrice();
        BigDecimal averagePrice = close;
        String averageType = null;
        if ("DAY".equals(stockPriceMonitoring.getAvgType())) {
            BinanceMinAverage binanceMinAverage = binanceMinAverageMapper.selectBinanceMinAverageByCodeAndTime(code, DateUtils.getFormatTime(time));
            averagePrice = binanceMinAverage.getPrice();
            averageType = "24时";
        }
        if ("HOUR".equals(stockPriceMonitoring.getAvgType())) {
            BinanceHourAverage binanceHourAverage = binanceHourAverageMapper.selectBinanceHourAverageByCodeAndTime(code, DateUtils.getFormatTime(time));
            averagePrice = binanceHourAverage.getPrice();
            averageType = "60分";
        }
        if ("MIN30".equals(stockPriceMonitoring.getAvgType())) {
            Binance30minAverage binance30minAverage = binance30minAverageMapper.selectBinance30minAverageByCodeAndTime(code, DateUtils.getFormatTime(time));
            averagePrice = binance30minAverage.getPrice();
            averageType = "30分";
        }
        if ("MIN15".equals(stockPriceMonitoring.getAvgType())) {
            Binance15minAverage binance15minAverage = binance15minAverageMapper.selectBinance15minAverageByCodeAndTime(code, DateUtils.getFormatTime(time));
            averagePrice = binance15minAverage.getPrice();
            averageType = "15分";
        }
        if("MIN15_DAY".equals(stockPriceMonitoring.getAvgType())){
            averagePrice = binance15minDayAve.getPrice();
            averageType = "15分_24时";
        }
        //获取上一分钟的收盘价
        BigDecimal lastClose = open;
        BinanceMinK minK = stockMinKMapper.selectBinanceMinKByCodeAndTime(code, DateUtils.getFormatTime(DateUtils.addMinutes(time, -1)));
        if (minK != null && minK.getClose() != null) {
            lastClose = minK.getClose();
        }
        //收盘价大于日均价 为多行情
        if (close.compareTo(averagePriceDay) > 0) {
            //(日均价-收盘价)/日均价的绝对值 <= 0.001
            if (averagePriceDay.subtract(close).divide(averagePriceDay, 10, RoundingMode.HALF_UP).abs().compareTo(new BigDecimal("0.001")) <= 0) {
                //触发止损
                BinanceTransactionConf binanceTransactionConf = binanceTransactionConfMapper.selectBinanceTransactionConfById(confId);
                if (binanceTransactionConf != null && binanceTransactionConf.getCoinNumber().compareTo(BigDecimal.ZERO) > 0
                        && !"SELL".equals(binanceTransactionConf.getSide())) {
                    BinanceTransactionConf bean = new BinanceTransactionConf();
                    bean.setId(binanceTransactionConf.getId());
                    bean.setSide("SELL");
                    binanceTransactionConfMapper.updateBinanceTransactionConf(bean);

                    BinanceTransactionOrder order = new BinanceTransactionOrder();
                    order.setCode(code);
                    order.setOrgOrderId(IdUtil.getSnowflakeNextIdStr());
                    order.setQuantity(binanceTransactionConf.getCoinNumber());
                    order.setSide("SELL");
                    order.setType("MARKET");
                    order.setConfigId(confId);
                    order.setCreateTime(time);
                    order.setRemark("系统止损");
                    int save = binanceTransactionOrderMapper.insertBinanceTransactionOrder(order);
                    if (save > 0) {
                        //调用下单接口
                        JSONObject res = OrderApi.order(order);
                        if (StringUtils.isNotBlank(res.getString("code"))) {
                            order.setStatus("REJECTED");
                            order.setRemark(res.getString("msg"));
                        } else {
                            order.setStatus("PENDING_NEW");
                            order.setOrderId(res.getString("orderId"));
                        }
                        binanceTransactionOrderMapper.updateBinanceTransactionOrder(order);
                    }
                }
                return;
            }
            //收盘价小于均价 并且(均价-收盘价)/均价 >= 下破配置 && 收盘价>=上次收盘价
            if (close.compareTo(averagePrice) < 0) {
                if ((averagePrice.subtract(close).divide(averagePrice, 10, RoundingMode.HALF_UP)).compareTo(stockPriceMonitoring.getBreDown().divide(new BigDecimal("100"))) >= 0
                        && close.compareTo(lastClose) >= 0) {
                    if (dingdingMessage) {
                        //查找当天是否存在相同的消息
                        BinanceDingdingMessage stockDingdingMessage = stockDingdingMessageMapper.selectDingdingMessageByLast(code, "average", "all");
                        if (stockDingdingMessage == null || !"买入".equals(stockDingdingMessage.getSignalType())) {
                            // 下破配置通知
                            String message = DingDingSendMsgUtils.getAveragePriceTemplate("多行情-买入", code,
                                    averagePrice.toString(), close.toString(), stockPriceMonitoring.getBreDown().toString(), DateUtil.formatDateTime(time), averageType);
                            DingDingSendMsgUtils.sendMessageAtAll(message);
                            //保存通知记录
                            BinanceDingdingMessage bean = new BinanceDingdingMessage();
                            bean.setCode(code);
                            bean.setMessageType("average");
                            bean.setSignalType("买入");
                            bean.setMessageBy("all");
                            bean.setCreateTime(new Date());
                            stockDingdingMessageMapper.insertBinanceDingdingMessage(bean);
                        }
                    }
                    //进行下单
                    BinanceTransactionConf binanceTransactionConf = binanceTransactionConfMapper.selectBinanceTransactionConfById(confId);
                    if (binanceTransactionConf != null && binanceTransactionConf.getUsdtNumber().compareTo(BigDecimal.ZERO) > 0
                            && !"BUY".equals(binanceTransactionConf.getSide())) {
                        BinanceTransactionConf bean = new BinanceTransactionConf();
                        bean.setId(binanceTransactionConf.getId());
                        bean.setSide("BUY");
                        binanceTransactionConfMapper.updateBinanceTransactionConf(bean);

                        BinanceTransactionOrder order = new BinanceTransactionOrder();
                        order.setCode(code);
                        order.setOrgOrderId(IdUtil.getSnowflakeNextIdStr());
                        order.setQuoteOrderQty(binanceTransactionConf.getUsdtNumber());
                        order.setSide("BUY");
                        order.setType("MARKET");
                        order.setConfigId(confId);
                        order.setCreateTime(time);
                        order.setRemark("自动交易");
                        int save = binanceTransactionOrderMapper.insertBinanceTransactionOrder(order);
                        if (save > 0) {
                            //调用下单接口
                            JSONObject res = OrderApi.order(order);
                            if (StringUtils.isNotBlank(res.getString("code"))) {
                                order.setStatus("REJECTED");
                                order.setRemark(res.getString("msg"));
                            } else {
                                order.setStatus("PENDING_NEW");
                                order.setOrderId(res.getString("orderId"));
                            }
                            binanceTransactionOrderMapper.updateBinanceTransactionOrder(order);
                        }
                    }
                }
            }

            //收盘价大于均价 并且(收盘价-均价)/均价 >= 上穿配置 && 开盘价>=上次收盘价
            if (close.compareTo(averagePrice) > 0) {
                if ((close.subtract(averagePrice).divide(averagePrice, 3, RoundingMode.HALF_UP)).compareTo(stockPriceMonitoring.getBreAbove().divide(new BigDecimal("100"))) >= 0
                        && open.compareTo(lastClose) >= 0) {
                    if (dingdingMessage) {
                        BinanceDingdingMessage stockDingdingMessage = stockDingdingMessageMapper.selectDingdingMessageByLast(code, "average", "all");
                        if (stockDingdingMessage == null || !"卖出".equals(stockDingdingMessage.getSignalType())) {
                            // 上穿配置通知
                            String message = DingDingSendMsgUtils.getAveragePriceTemplate("多行情-卖出", code,
                                    averagePrice.toString(), close.toString(), stockPriceMonitoring.getBreAbove().toString(), DateUtil.formatDateTime(time), averageType);
                            DingDingSendMsgUtils.sendMessageAtAll(message);
                            //保存通知记录
                            BinanceDingdingMessage bean = new BinanceDingdingMessage();
                            bean.setCode(code);
                            bean.setMessageType("average");
                            bean.setSignalType("卖出");
                            bean.setMessageBy("all");
                            bean.setCreateTime(new Date());
                            stockDingdingMessageMapper.insertBinanceDingdingMessage(bean);
                        }
                    }
                    //进行下单
                    BinanceTransactionConf binanceTransactionConf = binanceTransactionConfMapper.selectBinanceTransactionConfById(confId);
                    if (binanceTransactionConf != null && binanceTransactionConf.getCoinNumber().compareTo(BigDecimal.ZERO) > 0
                            && !"SELL".equals(binanceTransactionConf.getSide())) {
                        BinanceTransactionConf bean = new BinanceTransactionConf();
                        bean.setId(binanceTransactionConf.getId());
                        bean.setSide("SELL");
                        binanceTransactionConfMapper.updateBinanceTransactionConf(bean);

                        BinanceTransactionOrder order = new BinanceTransactionOrder();
                        order.setCode(code);
                        order.setOrgOrderId(IdUtil.getSnowflakeNextIdStr());
                        order.setQuantity(binanceTransactionConf.getCoinNumber());
                        order.setSide("SELL");
                        order.setType("MARKET");
                        order.setConfigId(confId);
                        order.setCreateTime(time);
                        order.setRemark("自动交易");
                        int save = binanceTransactionOrderMapper.insertBinanceTransactionOrder(order);
                        if (save > 0) {
                            //调用下单接口
                            JSONObject res = OrderApi.order(order);
                            if (StringUtils.isNotBlank(res.getString("code"))) {
                                order.setStatus("REJECTED");
                                order.setRemark(res.getString("msg"));
                            } else {
                                order.setStatus("PENDING_NEW");
                                order.setOrderId(res.getString("orderId"));
                            }
                            binanceTransactionOrderMapper.updateBinanceTransactionOrder(order);
                        }
                    }
                }
            }
        }
        //收盘价小于日均价 为空行情
        if (close.compareTo(averagePriceDay) < 0) {
            //收盘价小于均价 并且(均价-收盘价)/均价 >= 下破配置 && 收盘价>=上次收盘价
            if (close.compareTo(averagePrice) < 0) {
                if ((averagePrice.subtract(close).divide(averagePrice, 10, RoundingMode.HALF_UP)).compareTo(stockPriceMonitoring.getFallBreDown().divide(new BigDecimal("100"))) >= 0
                        && close.compareTo(lastClose) >= 0) {
                    if (dingdingMessage) {
                        //查找当天是否存在相同的消息
                        BinanceDingdingMessage stockDingdingMessage = stockDingdingMessageMapper.selectDingdingMessageByLast(code, "average", "all");
                        if (stockDingdingMessage == null || !"买入".equals(stockDingdingMessage.getSignalType())) {
                            // 下破配置通知
                            String message = DingDingSendMsgUtils.getAveragePriceTemplate("空行情-买入", code,
                                    averagePrice.toString(), close.toString(), stockPriceMonitoring.getFallBreDown().toString(), DateUtil.formatDateTime(time), averageType);
                            DingDingSendMsgUtils.sendMessageAtAll(message);
                            //保存通知记录
                            BinanceDingdingMessage bean = new BinanceDingdingMessage();
                            bean.setCode(code);
                            bean.setMessageType("average");
                            bean.setSignalType("买入");
                            bean.setMessageBy("all");
                            bean.setCreateTime(new Date());
                            stockDingdingMessageMapper.insertBinanceDingdingMessage(bean);
                        }
                    }
                    //进行下单
                    BinanceTransactionConf binanceTransactionConf = binanceTransactionConfMapper.selectBinanceTransactionConfById(confId);
                    if (binanceTransactionConf != null && binanceTransactionConf.getUsdtNumber().compareTo(BigDecimal.ZERO) > 0
                            && !"BUY".equals(binanceTransactionConf.getSide())) {
                        BinanceTransactionConf bean = new BinanceTransactionConf();
                        bean.setId(binanceTransactionConf.getId());
                        bean.setSide("BUY");
                        binanceTransactionConfMapper.updateBinanceTransactionConf(bean);

                        BinanceTransactionOrder order = new BinanceTransactionOrder();
                        order.setCode(code);
                        order.setOrgOrderId(IdUtil.getSnowflakeNextIdStr());
                        order.setQuoteOrderQty(binanceTransactionConf.getUsdtNumber());
                        order.setSide("BUY");
                        order.setType("MARKET");
                        order.setConfigId(confId);
                        order.setCreateTime(time);
                        order.setRemark("自动交易");
                        int save = binanceTransactionOrderMapper.insertBinanceTransactionOrder(order);
                        if (save > 0) {
                            //调用下单接口
                            JSONObject res = OrderApi.order(order);
                            if (StringUtils.isNotBlank(res.getString("code"))) {
                                order.setStatus("REJECTED");
                                order.setRemark(res.getString("msg"));
                            } else {
                                order.setStatus("PENDING_NEW");
                                order.setOrderId(res.getString("orderId"));
                            }
                            binanceTransactionOrderMapper.updateBinanceTransactionOrder(order);
                        }
                    }
                }
            }

            //收盘价大于均价 并且(收盘价-均价)/均价 >= 上穿配置 && 开盘价>=上次收盘价
            if (close.compareTo(averagePrice) > 0) {
                if ((close.subtract(averagePrice).divide(averagePrice, 3, RoundingMode.HALF_UP)).compareTo(stockPriceMonitoring.getFallBreAbove().divide(new BigDecimal("100"))) >= 0
                        && open.compareTo(lastClose) >= 0) {
                    if (dingdingMessage) {
                        BinanceDingdingMessage stockDingdingMessage = stockDingdingMessageMapper.selectDingdingMessageByLast(code, "average", "all");
                        if (stockDingdingMessage == null || !"卖出".equals(stockDingdingMessage.getSignalType())) {
                            // 上穿配置通知
                            String message = DingDingSendMsgUtils.getAveragePriceTemplate("空行情-卖出", code,
                                    averagePrice.toString(), close.toString(), stockPriceMonitoring.getFallBreAbove().toString(), DateUtil.formatDateTime(time), averageType);
                            DingDingSendMsgUtils.sendMessageAtAll(message);
                            //保存通知记录
                            BinanceDingdingMessage bean = new BinanceDingdingMessage();
                            bean.setCode(code);
                            bean.setMessageType("average");
                            bean.setSignalType("卖出");
                            bean.setMessageBy("all");
                            bean.setCreateTime(new Date());
                            stockDingdingMessageMapper.insertBinanceDingdingMessage(bean);
                        }
                    }
                    //进行下单
                    BinanceTransactionConf binanceTransactionConf = binanceTransactionConfMapper.selectBinanceTransactionConfById(confId);
                    if (binanceTransactionConf != null && binanceTransactionConf.getCoinNumber().compareTo(BigDecimal.ZERO) > 0
                            && !"SELL".equals(binanceTransactionConf.getSide())) {
                        BinanceTransactionConf bean = new BinanceTransactionConf();
                        bean.setId(binanceTransactionConf.getId());
                        bean.setSide("SELL");
                        binanceTransactionConfMapper.updateBinanceTransactionConf(bean);

                        BinanceTransactionOrder order = new BinanceTransactionOrder();
                        order.setCode(code);
                        order.setOrgOrderId(IdUtil.getSnowflakeNextIdStr());
                        order.setQuantity(binanceTransactionConf.getCoinNumber());
                        order.setSide("SELL");
                        order.setType("MARKET");
                        order.setConfigId(confId);
                        order.setCreateTime(time);
                        order.setRemark("自动交易");
                        int save = binanceTransactionOrderMapper.insertBinanceTransactionOrder(order);
                        if (save > 0) {
                            //调用下单接口
                            JSONObject res = OrderApi.order(order);
                            if (StringUtils.isNotBlank(res.getString("code"))) {
                                order.setStatus("REJECTED");
                                order.setRemark(res.getString("msg"));
                            } else {
                                order.setStatus("PENDING_NEW");
                                order.setOrderId(res.getString("orderId"));
                            }
                            binanceTransactionOrderMapper.updateBinanceTransactionOrder(order);
                        }
                    }
                }
            }
        }
    }
}
